#ifndef _MAPOBJECT_H_
#define _MAPOBJECT_H_

#include "INamable.h"
#include "IRepresentable.h"
#include "IMovable.h"
#include "ILiving.h"
#include "ISolid.h"
#include "IDoesDamage.h"
#include "IHasMonster.h"

/**
 * Defines an map object.
 *
 * A map object can be a floor, a wall or an exit.
 */
class MapObject
{
private:
  /**
   * Holder for name.
   */
  INamable* name;

  /**
   * Holder for representation.
   */
  IRepresentable* representation;

  /**
   * Holder for object position.
   */
  IMovable* move;

  /**
   * Holder for objects life.
   */
  ILiving* life;

  /**
   * Holder for objects solidness.
   */
  ISolid* solid;

  /**
   * Holder for the damage behaviour.
   */
  IDoesDamage* dmg;

  /**
   * Defines the monster associated to this map object.
   */ 
  IHasMonster* monster;

public:
  /**
   * Basic constructor. Just provide appropiate objects to define
   * the map object behaviour.
   *
   * @arg[in] n : Will define the map object's name
   * @arg[in] r : Will define map object's representation
   * @arg[in] m : Will define map object's position
   * @arg[in] l : Will define monster's livibility
   * @arg[in] s : Defines the object solidness
   * @arg[in] d : Defines how much damage the object can deal
   * @arg[in] mst : Defines the monsters that are attached to object
   */
  MapObject(INamable* n, IRepresentable* r, IMovable* m,
            ILiving* l, ISolid* s, IDoesDamage* d, IHasMonster* mst) :
            name(n), representation(r), move(m), life(l), solid(s),
            dmg(d), monster(mst) {}

  /**
   * Returns the map object's name.
   *
   * @return The map object's name
   */
  const std::string& getName() const { return name->getName(); }

  /**
   * Gets the ASCII representation of the map object.
   *
   * @return The ASCII representation of the map object
   */
  char getAsciiRepresentation() const { return representation->getAsciiRepresentation(); }

  /**
   * Gets the map object's health.
   *
   * @return The map object's health.
   */
  int getHealth() const { return life->getHealth(); }

  /**
   * Hurts the map objects by a given amount.
   *
   * @arg[in] h : Damage that will be dealt to map object
   */
  void hurt(int h) { life->hurt(h); }

  /**
   * Heals the map object by a given amount.
   *
   * @arg[in] h : Heals the map object by a given amount
   */
  void heal(int h) { life->heal(h); }

  /**
   * Gets the position of the map object.
   *
   * @return The position of the map object
   */
  const IMovable::movableVector& getPosition() const { return move->getPosition(); }

  /**
   * Sets the position of the map object.
   *
   * @arg[in] v : The position of the map object to be set
   */
  void setPosition(const IMovable::movableVector& v) { move->setPosition(v); }

  /**
   * Moves the object by a given vector.
   *
   * @arg[in] v : Vector that will move the object
   */
  void movePosition(const IMovable::movableVector& v) { move->movePosition(v); }

  /**
   * Tells us if object is solid or not.
   *
   * @return true if object is solid, false otherwise
   */
  bool isSolid() { return solid->isSolid(); }

  /**
   * The amount of damage the object can deal.
   *
   * @return The amount of damage the object deals
   */
  int doDamage() { return dmg->doDamage(); }

  /**
   * Set a monster associated to this map object.
   *
   * @arg[in] m: Monster to associate to this object
   */
  void setMonster(Monster* m) { monster->setMonster(m); }

  /**
   * Gets the monster associated to this map object.
   *
   * @return Monster associated to this object.
   */
  Monster* getMonster() { return monster->getMonster(); }
  
};
#endif /* _MAPOBJECT_H_ */

